/*
 * @file     g_timer.c
 * @brief    source file for setting timer
 *
 * Change Logs:
 * Date            Author             Version        Notes
 * 2020-12-29      wanghongwei        V1.0.0         the first version
 * 2021-12-08      dengzhiqian        V1.0.1         add rv delay
 */

#include "g_timer.h"

/* Exported functions -------------------------------------------------------*/
/**
 * @method  delay_ms
 * @brief   ms delay
 * @param   ms: time
 * @retval  none
 */

void delay_ms(int ms)
{
#ifdef	__USE_M0__
    ((void(*)(int))(FUNC_DELAY_MS_ADDR))(ms);
#else
    volatile uint32_t i = 48000*ms;
    while(i--);
#endif
}

/**
 * @method  delay_us
 * @brief   us delay
 * @param   us: time
 * @retval  none
 */

void delay_us(int us)
{
#ifdef	__USE_M0__
    ((void(*)(int))(FUNC_DELAY_US_ADDR))(us);
#else
    volatile uint32_t i = 48*us;
    while(i--);
#endif
}

/**
 * @method  G_TIM_Init
 * @brief   Init timer
 * @param   TIMMx : the timer moudle selection
 * @param   TIM_Init_Struct : TIM initializes the structure
 * @retval  none
 */
void G_TIM_Init(TIM_Module_TypeDef *TIMMx, G_TIM_InitTypeDef *TIM_Init_Struct)
{
    _ASSERT(IS_TIMER_NUM(TIM_Init_Struct->TIMx));
    _ASSERT(IS_TIMM(TIMMx));

    G_TIM_Cmd(TIMMx, TIM_Init_Struct->TIMx, DISABLE);

    TIMMx->PERIOD.reg[PCNT(TIM_Init_Struct->TIMx)] = TIM_Init_Struct->period;
    if (TIM_Init_Struct->TIMx < TIM8)
    {
        if ((TIM_Init_Struct->Auto_Reload) == DISABLE)
        {
            TIMMx->CTRL1.reg |= (TIM_CTRL_MODE << TIM_Init_Struct->TIMx * 4);
            TIMMx->CTRL1.reg &= ~(TIM_CTRL_AUTO_RELOAD << TIM_Init_Struct->TIMx * 4);
        }
        else
        {
            TIMMx->CTRL1.reg |= ((TIM_CTRL_MODE | TIM_CTRL_AUTO_RELOAD) << TIM_Init_Struct->TIMx * 4);
        }
    }
    else
    {
        if ((TIM_Init_Struct->Auto_Reload) == DISABLE)
        {
            TIMMx->CTRL2.reg |= TIM_CTRL_MODE;
            TIMMx->CTRL2.reg &= ~(TIM_CTRL_AUTO_RELOAD);
        }
        else
        {
            TIMMx->CTRL2.reg |= (TIM_CTRL_MODE | TIM_CTRL_AUTO_RELOAD);
        }
    }
}

/**
 * @method  G_TIM_DeInit
 * @brief   disable timer
 * @param   TIMMx : the timer moudle selection
 * @retval  none
 */
void G_TIM_DeInit(TIM_Module_TypeDef *TIMMx)
{
    _ASSERT(IS_TIMM(TIMMx));

    TIMMx->CTRL1.reg = 0;
    TIMMx->CTRL2.reg = 0;
}

/**
 * @method  G_TIM_Cmd
 * @brief   enable or disable timer
 * @param   TIMMx : the timer moudle selection
 * @param   TIMx : the timer number,TIM0-TIM8
 * @param   NewState :Fixed G_FunctionalState enumeration type
 * @retval  none
 */
void G_TIM_Cmd(TIM_Module_TypeDef *TIMMx, G_TIM_NumTypeDef TIMx, G_FunctionalState NewState)
{

    _ASSERT(IS_TIMM(TIMMx));
    _ASSERT(IS_TIMER_NUM(TIMx));

    if (ENABLE == NewState)
    {
        if (TIMx < TIM8)
        {
            TIMMx->CTRL1.reg |= (TIM_CTRL_ENABLE << TIMx * 4);
        }
        else
        {
            TIMMx->CTRL2.reg |= (TIM_CTRL_ENABLE);
        }
    }
    else if (DISABLE == NewState)
    {
        if (TIMx < TIM8)
        {
            TIMMx->CTRL1.reg &= ~(TIM_CTRL_ENABLE << TIMx * 4);
        }
        else
        {
            TIMMx->CTRL2.reg &= ~(TIM_CTRL_ENABLE);
        }
    }
}

/**
 * @method  G_TIM_ModeConfig
 * @brief   Configure timer Period
 * @param   TIMMx : the timer moudle selection
 * @param   TIMx : the timer number,TIM0-TIM8
 * @param   TIM_Mode :TIM or PWM
 * @retval  none
 */
void G_TIM_ModeConfig(TIM_Module_TypeDef *TIMMx, G_TIM_NumTypeDef TIMx, G_TIM_ModeTypeDef TIM_Mode)
{
    _ASSERT(IS_TIMM(TIMMx));
    _ASSERT(IS_TIMER_NUM(TIMx));
    _ASSERT(IS_TIM_MODE(TIM_Mode));

    if (TIM_Mode == TIM_Mode_TIMER)
    {
        if (TIMx < TIM8)
        {
            TIMMx->CTRL1.reg |= (TIM_CTRL_MODE << TIMx * 4);
        }
        else
        {
            TIMMx->CTRL2.reg |= (TIM_CTRL_MODE);
        }
    }
    else
    {
        if (TIMx < TIM8)
        {
            TIMMx->CTRL1.reg &= ~(TIM_CTRL_MODE << TIMx * 4);
        }
        else
        {
            TIMMx->CTRL2.reg &= ~(TIM_CTRL_MODE);
        }
    }
}

/**
 * @method  G_TIM_SetPeriod
 * @brief   Initialize TIMx into PWM mode,only Initialize,use G_TIM_Cmd start putout PWM
 * @param   TIMMx : the timer moudle selection
 * @param   TIMx : the timer number,TIM0-TIM8
 * @param   Period : set period value
 * @retval none
 */
void G_TIM_SetPeriod(TIM_Module_TypeDef *TIMMx, G_TIM_NumTypeDef TIMx, uint32_t Period)
{
    _ASSERT(IS_TIMER_NUM(TIMx));
    _ASSERT(IS_TIMM(TIMMx));

    TIMMx->PERIOD.reg[PCNT(TIMx)] = Period;
}

/**
 * @method G_TIM_PWMInit
 * @brief  Configure PWM Period
 * @param  TIMMx : the timer moudle selection
 * @param  PWM_init_struct : PWM initializes the structure
 * @retval none
 */
void G_TIM_PWMInit(TIM_Module_TypeDef *TIMMx, G_PWM_InitTypeDef *TIM_PWMInitStruct)
{
    _ASSERT(IS_TIMM(TIMMx));
    _ASSERT(IS_TIMER_NUM(TIM_PWMInitStruct->TIMx));

    G_TIM_Cmd(MTIM, TIM_PWMInitStruct->TIMx, DISABLE);

    TIMMx->PERIOD.reg[PCNT(TIM_PWMInitStruct->TIMx)] = TIM_PWMInitStruct->HighLevelPeriod;
    TIMMx->PERIOD.reg[NCNT(TIM_PWMInitStruct->TIMx)] = TIM_PWMInitStruct->LowLevelPeriod;

    if (HIGH_LEVEL == TIM_PWMInitStruct->StartLevel)
    {
        if (TIM_PWMInitStruct->TIMx < TIM8)
        {
            TIMMx->CTRL1.reg |= (TIM_CTRL_START_LEVEL << TIM_PWMInitStruct->TIMx * 4);
        }
        else
        {
            TIMMx->CTRL2.reg |= (TIM_CTRL_START_LEVEL);
        }
    }
    else
    {
        if (TIM_PWMInitStruct->TIMx < TIM8)
        {
            TIMMx->CTRL1.reg &= ~(TIM_CTRL_START_LEVEL << TIM_PWMInitStruct->TIMx * 4);
        }
        else
        {
            TIMMx->CTRL2.reg &= ~(TIM_CTRL_START_LEVEL);
        }
    }

    if (TIM_PWMInitStruct->TIMx < TIM8)
    {
        TIMMx->CTRL1.reg &= ~(TIM_CTRL_MODE << (TIM_PWMInitStruct->TIMx * 4));
    }
    else
    {
        TIMMx->CTRL2.reg &= ~(TIM_CTRL_MODE);
    }
}

/**
 * @method G_TIM_SetPWMPeriod
 * @brief  Configure PWM Differential output
 * @param  TIMMx : the timer moudle selection
 * @param  TIMx : the timer number of output PWM(TIM0-TIM8)
 * @param  LowLevelPeriod :the PWM low level Period(Reload value)
 * @param  HighLevelPeriod :the PWM high level Period(Reload value)
 * @retval none
 */
void G_TIM_SetPWMPeriod(TIM_Module_TypeDef *TIMMx, G_TIM_NumTypeDef TIMx, uint32_t LowLevelPeriod, uint32_t HighLevelPeriod)
{
    _ASSERT(IS_TIMM(TIMMx));
    _ASSERT(IS_TIMER_NUM(TIMx));

    TIMMx->PERIOD.reg[PCNT(TIMx)] = HighLevelPeriod;
    TIMMx->PERIOD.reg[NCNT(TIMx)] = LowLevelPeriod;
}

/**
 * @method G_TIM_ITConfig
 * @brief  Enable or disable the TIM interrupt
 * @param  TIMMx : the timer moudle selection
 * @param  TIMx : the timer number of output PWM1(TIM0-TIM8)
 * @param  NewState :Fixed G_FunctionalState enumeration type
 * @retval none
 */
void G_TIM_ITConfig(TIM_Module_TypeDef *TIMMx, G_TIM_NumTypeDef TIMx, G_FunctionalState NewState)
{
    _ASSERT(IS_TIMM(TIMMx));
    _ASSERT(IS_TIMER_NUM(TIMx));

    if (NewState == ENABLE)
    {
        TIMMx->CTRL2.bit.IRQ_EN |= BIT(TIMx);
    }
    else
    {
        TIMMx->CTRL2.bit.IRQ_EN &= ~(BIT(TIMx));
    }
}

/**
 * @method G_TIM_ClearITPendingBit
 * @brief  Clear the TIM interrupt
 * @param  TIMMx : the timer moudle selection
 * @param  TIMx : the timer number of output PWM1(TIM0-TIM8)
 * @retval none
 */
void G_TIM_ClearITPendingBit(TIM_Module_TypeDef *TIMMx, G_TIM_NumTypeDef TIMx)
{
    _ASSERT(IS_TIMM(TIMMx));
    _ASSERT(IS_TIMER_NUM(TIMx));

    TIMMx->CTRL2.bit.IRQ_CLR |= BIT(TIMx);
    TIMMx->CTRL2.bit.IRQ_CLR = 0;
}

/**
 * @method G_TIM_GetITStatus
 * @brief  Get the specific TIM interrupt status
 * @param  TIMMx : the timer moudle selection
 * @param  TIMx : the timer number of output PWM1(TIM0-TIM8)
 * @retval The new state of specific TIM IT_Flag(SET or RESET)
 */
G_ITStatus G_TIM_GetITStatus(TIM_Module_TypeDef *TIMMx, G_TIM_NumTypeDef TIMx)
{
    _ASSERT(IS_TIMM(TIMMx));
    _ASSERT(IS_TIMER_NUM(TIMx));

    if ((TIMMx->IRQ_NUM.bit.PWM_IRQ_PEND & BIT(TIMx)) != RESET)
    {
        return SET;
    }
    return RESET;
}

/**
 * @method G_TIM_GetAllITStatus
 * @brief  Get all TIM interrupt status
 * @param  TIMMx : the timer moudle selection
 * @retval The new state of TIM IT_Flag
 */
uint32_t G_TIM_GetAllITStatus(TIM_Module_TypeDef *TIMMx)
{
    _ASSERT(IS_TIMM(TIMMx));

    return TIMMx->IRQ_NUM.bit.PWM_IRQ_PEND;
}

/************************ (C) COPYRIGHT GKT *****END OF FILE****/
